package service

import java.io.IOException
import java.util.UUID

import config.SSLProperties
import model.request.{PayRequest, WXOrderQueryRequest, WXPayCloseRequest, WXPayRefundRequest, WXPayRequest, WXRefundQueryRequest, WXSignkeyRequest}
import model.response.{WXOrderQueryResponse, WXPayCloseResponse, WXPayRefundResponse, WXPayResponse, WXRefundQueryResponse, WXSignkeyResponse}
import okhttp3.{MediaType, OkHttpClient, RequestBody}
import remoting.WXPayRemoting
import retrofit2.{Response, Retrofit}
import retrofit2.converter.simplexml.SimpleXmlConverterFactory
import utils.{BuildDataUtil, RandomUtil, SignatureUtil, XmlUtil}

class WXPayService(gateway: String, appId: String, appSecret: String, mchId: String, mchKey: String) {
  /*微信支付预下单接口*/
  def appPrePay(req: PayRequest): WXPayResponse = {
    val wxPayReq = new WXPayRequest
    wxPayReq.outTradeNo = req.orderNO
    wxPayReq.totalFee = req.amount
    wxPayReq.body = req.goodsName
    wxPayReq.attach = req.attach
    wxPayReq.spbillCreateIp = req.spbillCreateIp
    wxPayReq.tradeType = "APP"
    wxPayReq.timeExpire = req.timeExpire
    wxPayReq.notifyUrl = req.notifyUrl
    unifiedOrder(wxPayReq)
  }

  /*微信支付统一下单*/
  def unifiedOrder(wxPayReq: WXPayRequest) = { //配置秘钥信息
    wxPayReq.appid = appId
    wxPayReq.mchId = mchId
    wxPayReq.nonceStr = RandomUtil.getRandomStr
    val signKey = mchKey
    /*if(!getGateway().endsWith(SANDBOXNEW)){
                signKey = getSignKey();
            }*/
    //签名
    wxPayReq.sign = SignatureUtil.sign(BuildDataUtil.buildMap(wxPayReq), signKey)

    val retrofit = new Retrofit.Builder()
      .baseUrl(gateway)
      //xml转化器   SimpleXmlConverterFactory 需要另外添加依赖  不在retrofit2中
      .addConverterFactory(SimpleXmlConverterFactory.create())
      .build();

    val xml = XmlUtil.toXMl(wxPayReq)
    val body = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml)
    val call = retrofit.create(classOf[WXPayRemoting]).unifiedOrder(body)
    var retrofitResponse:Response[WXPayResponse]  = null
    try retrofitResponse = call.execute
    catch {
      case e: IOException =>
        e.printStackTrace()
    }
    if (!retrofitResponse.raw.isSuccessful) throw new RuntimeException("【微信统一支付】发起支付, 网络异常")
    val response = retrofitResponse.body
    if (!(response.returnCode == "SUCCESS")) throw new RuntimeException("【微信统一支付】发起支付, returnCode != SUCCESS, returnMsg = " + response.returnMsg)
    response
  }

  /*微信支付查询接口*/
  def query(wxOrderQueryReq: WXOrderQueryRequest): WXOrderQueryResponse = {
    wxOrderQueryReq.appid = appId
    wxOrderQueryReq.mchId = mchId
    wxOrderQueryReq.nonceStr = RandomUtil.getRandomStr
    val signKey = mchKey
    wxOrderQueryReq.sign = SignatureUtil.sign(BuildDataUtil.buildMap(wxOrderQueryReq), signKey)

    val retrofit = new Retrofit.Builder()
      .baseUrl(gateway)
      //xml转化器   SimpleXmlConverterFactory 需要另外添加依赖  不在retrofit2中
      .addConverterFactory(SimpleXmlConverterFactory.create())
      .build();

    val xml = XmlUtil.toXMl(wxOrderQueryReq)
    val body = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml)
    val call = retrofit.create(classOf[WXPayRemoting]).query(body)
    var retrofitResponse: Response[WXOrderQueryResponse] = null
    try retrofitResponse = call.execute
    catch {
      case e: IOException =>
        e.printStackTrace()
    }
    if (!retrofitResponse.raw.isSuccessful) throw new RuntimeException("【微信支付订单查询】查询失败, 网络异常")
    val response = retrofitResponse.body
    if (!(response.returnCode == "SUCCESS")) throw new RuntimeException("【微信统一支付】发起支付, returnCode != SUCCESS, returnMsg = " + response.returnMsg)
    response
  }

  /*微信支付交易关单接口*/
  def closeOrder(wxPayCloseReq: WXPayCloseRequest): WXPayCloseResponse = {
    wxPayCloseReq.appid = appId
    wxPayCloseReq.mchId = mchId
    wxPayCloseReq.nonceStr = RandomUtil.getRandomStr
    val signKey = mchKey
    /* if(!getGateway().endsWith(SANDBOXNEW)){
        signKey = getSignKey();
     }*/
    wxPayCloseReq.sign = SignatureUtil.sign(BuildDataUtil.buildMap(wxPayCloseReq), signKey)

    val retrofit = new Retrofit.Builder().baseUrl(gateway)
      .addConverterFactory(SimpleXmlConverterFactory.create) //xml转化器   SimpleXmlConverterFactory 需要另外添加依赖  不在retrofit2中
      .build
    val xml = XmlUtil.toXMl(wxPayCloseReq)
    val body = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml)
    val call = retrofit.create(classOf[WXPayRemoting]).closeOrder(body)
    var retrofitResponse:Response[WXPayCloseResponse] = null
    try retrofitResponse = call.execute
    catch {
      case e: IOException =>
        e.printStackTrace()
    }
    if (!retrofitResponse.isSuccessful) throw new RuntimeException("【微信支付退款订单查询】查询失败, 网络异常")
    retrofitResponse.body
  }

  /*微信支付退款接口*/
  def refund(wxPayRefundReq: WXPayRefundRequest, keyPath: String): WXPayRefundResponse = {
    val signKey = mchKey
    wxPayRefundReq.sign = SignatureUtil.sign(BuildDataUtil.buildMap(wxPayRefundReq), signKey)
    //初始化证书
    val sslProperties = new SSLProperties(mchId, mchKey)
    if (sslProperties.sslContext == null) sslProperties.initSSLContext(keyPath)
    val okHttpClient = new OkHttpClient().newBuilder.sslSocketFactory(sslProperties.sslContext.getSocketFactory)
    val retrofit = new Retrofit.Builder().baseUrl(gateway).addConverterFactory(SimpleXmlConverterFactory.create).client(okHttpClient.build).build
    val xml = XmlUtil.toXMl(wxPayRefundReq)
    //System.out.println("refund request body ；" + xml)
    val body = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml)
    val call = retrofit.create(classOf[WXPayRemoting]).refund(body)
    var retrofitResponse:Response[WXPayRefundResponse] = null
    try retrofitResponse = call.execute
    catch {
      case e: IOException =>
        e.printStackTrace()
    }
    if (!retrofitResponse.isSuccessful) throw new RuntimeException("【微信退款】发起退款, 网络异常")
    retrofitResponse.body
  }

  /*微信支付退款查询接口*/
  def refundQuery(wxRefundQueryReq: WXRefundQueryRequest): WXRefundQueryResponse = {
    wxRefundQueryReq.appid = appId
    wxRefundQueryReq.mchId = mchId
    wxRefundQueryReq.nonceStr = RandomUtil.getRandomStr
    val signKey = mchKey
    wxRefundQueryReq.sign = SignatureUtil.sign(BuildDataUtil.buildMap(wxRefundQueryReq), signKey)
    /*if(!getGateway().endsWith(SANDBOXNEW)){
      signKey = getSignKey();
    }*/
    val retrofit = new Retrofit.Builder().baseUrl(gateway)
      .addConverterFactory(SimpleXmlConverterFactory.create) //xml转化器   SimpleXmlConverterFactory 需要另外添加依赖  不在retrofit2中
      .build
    val xml = XmlUtil.toXMl(wxRefundQueryReq)
    val body = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml)
    val call = retrofit.create(classOf[WXPayRemoting]).refundQuery(body)
    var retrofitResponse:Response[WXRefundQueryResponse] = null
    try retrofitResponse = call.execute
    catch {
      case e: IOException =>
        e.printStackTrace()
    }
    if (!retrofitResponse.isSuccessful) throw new RuntimeException("【微信支付退款订单查询】查询失败, 网络异常")
    retrofitResponse.body
  }

  /*沙箱环境获取微信沙箱密钥*/
  def getSignKey: String = {
    val signkeyReq = new WXSignkeyRequest
    signkeyReq.mchId = mchId
    signkeyReq.nonceStr = UUID.randomUUID.toString.replaceAll("-", "")
    signkeyReq.sign = SignatureUtil.sign(BuildDataUtil.buildMap(signkeyReq), mchKey)
    val retrofit = new Retrofit.Builder().baseUrl(gateway)
      .addConverterFactory(SimpleXmlConverterFactory.create) //xml转化器   SimpleXmlConverterFactory 需要另外添加依赖  不在retrofit2中
      .build
    val xml = XmlUtil.toXMl(signkeyReq)
    val body = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml)
    val call = retrofit.create(classOf[WXPayRemoting]).getSignKey(body)
    var retrofitResponse:Response[WXSignkeyResponse] = null
    try retrofitResponse = call.execute
    catch {
      case e: IOException =>
        e.printStackTrace()
    }
    if (!retrofitResponse.isSuccessful) throw new RuntimeException("【微信沙箱】获取沙箱signKey, 网络异常")
    val response = retrofitResponse.body
    if (!(response.returnCode == "SUCCESS")) throw new RuntimeException("【微信沙箱】获取沙箱signKey, returnCode != SUCCESS, returnMsg = " + response.returnMsg)
    response.sandboxSignkey
  }
}
